package com.minyon_web_admin.shiro;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.minyon_utils.StringUtil;
import com.minyon_web_admin.model.SysMenuBean;
import com.minyon_web_admin.model.SysRoleBean;
import com.minyon_web_admin.model.SysUserBean;
import com.minyon_web_admin.server.ISysMenu;
import com.minyon_web_admin.server.ISysRole;
import com.minyon_web_admin.server.ISysUser;
import com.minyon_web_admin.service.SysUserService;
import com.minyon_web_admin.shiro.bean.LoginUser;

public class CustomRealm extends AuthorizingRealm {
	private LoginUser currentUser = null;
	@Autowired
	ISysUser userService;
	@Autowired
	ISysMenu menuService;
	@Autowired
	ISysRole roleService;
	protected final Logger minYonlogger = (Logger) LoggerFactory.getLogger(getClass());

	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
		minYonlogger.info("shiro验证权限 ");
		Session session = SecurityUtils.getSubject().getSession();
		LoginUser loginUser = (LoginUser) session.getAttribute("currentUser");
		return loginUser.getAuthorization();
	}

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		minYonlogger.info("shiro验证 登陆账号 ");
		// 获取用户名 、密码
		String userName = (String) token.getPrincipal();
		if (StringUtil.isEmpty(userName)) {
			throw new UnknownAccountException();
		}
		// 查询数据库用户信息
		Map<String, Object> reqMap = new HashMap<String, Object>();
		reqMap.put("loginName", userName);
		SysUserBean userInfo = (SysUserBean) userService.queryDetail(reqMap).get("RESULT");
		// String salt = new SecureRandomNumberGenerator().nextBytes().toHex();
		if (StringUtil.isEmpty(userInfo)) {
			minYonlogger.debug("登录验证信息为空");
			throw new UnknownAccountException();
		}
		String password = new String((char[]) token.getCredentials()); // 得到密码
		// 比较密码
		String inputPwd = PasswordHelper.encryptPassword2(userName, password, userInfo.getSalt());
		if (!inputPwd.equals(userInfo.getPassword())) {
			throw new IncorrectCredentialsException("密码不正确.");
		}
		currentUser = new LoginUser();
		currentUser.setLoginName(userName);
		currentUser.setMobile(userInfo.getMobile());
		currentUser.setName(userInfo.getName());
		currentUser.setUserId(String.valueOf(userInfo.getId()));
		setAuthor(currentUser.getUserId());
		setSessionInfo(currentUser);
		// 交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配，如果觉得人家的不好可以在此判断或自定义实现
		return new SimpleAuthenticationInfo(userInfo, userInfo.getPassword(), ByteSource.Util.bytes(userInfo
				.getLoginName() + userInfo.getSalt()),// username+salt
				getName());
	}

	/**
	 * 获取用户的授权.
	 * 
	 * @param userId
	 *            用户账户
	 */
	@SuppressWarnings("unchecked")
	private void setAuthor(String userId) {
		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
		List<SysMenuBean> menus = (List<SysMenuBean>) menuService.queryPermissionByUserId(userId).get("RESULT");
		List<SysRoleBean> roles = (List<SysRoleBean>) roleService.queryRoleByUserId(userId).get("RESULT");

		currentUser.setPermissionInfo(menus);
		currentUser.setRoleInfo(roles);
		// 添加shiro用户 权限
		for (SysMenuBean bean : menus) {
			authorizationInfo.addStringPermission(bean.getPermission());
		}
		// 添加shiro用户 权限
		for (SysRoleBean bean : roles) {
			authorizationInfo.addRole(bean.getRoleCode());
		}
		currentUser.setAuthorization(authorizationInfo);
		
	}

	/**
	 * 存放一些信息到session中，便于获取，可以通过httpsession获取相应的信息
	 * 
	 * @param user
	 */
	@SuppressWarnings("unused")
	private void setSessionInfo(LoginUser user) {
		Subject sub = SecurityUtils.getSubject();
		Session session = sub.getSession();
		session.setAttribute("currentUser", user);
	}
}
